package stream

import (
	"bytes"
	"context"
	"github.com/lishimeng/go-log"
	"io"
	"time"
)

type Client struct {
	buf             *bytes.Buffer
	stream          io.ReadWriteCloser
	ctx             context.Context
	timeoutListener func()
}

func New(ctx context.Context, ioStream io.ReadWriteCloser) *Client {
	c := &Client{}
	c.ctx = ctx
	c.buf = bytes.NewBuffer(nil)
	c.stream = ioStream
	return c
}

func (c *Client) BufLen() int {
	return c.buf.Len()
}

func (c *Client) Start() {
	go c.readLoop()
}

func (c *Client) readLoop() {
	var bs = make([]byte, 32)
	defer func() {
		//if r := recover(); r != nil {
		//	log.Info(r)
		//}
	}()
	defer func() {
		if c.stream != nil {
			_ = c.stream.Close()
		}
	}()
	for {
		select {
		case <-c.ctx.Done():
			return
		default:
			n, e := c.stream.Read(bs)
			if e != nil {
				log.Info(e)
				return // IO异常要停止
			}
			if n > 0 {
				n, e = c.buf.Write(bs[:n])
				if e != nil {
					log.Info(e)
					return
				}
				//log.Info("io stream recv [%d]%02x", n, bs[:n])
			} else {
				time.Sleep(time.Millisecond * 100)
			}
		}
	}
}

func (c *Client) Write(payload []byte) (n int, err error) {
	log.Info(">>%02x", payload)
	n, err = c.stream.Write(payload)
	if err != nil {
		return
	}
	return
}

func (c *Client) Read(bs []byte) (n int, err error) {
	n, err = c.buf.Read(bs)
	return
}
